package com.zxd.service.impl;

import com.zxd.core.Constant;
import com.zxd.dao.ModuleDao;
import com.zxd.dao.RoleModuleDao;
import com.zxd.entity.Module;
import com.zxd.entity.Role;
import com.zxd.entity.RoleModule;
import com.zxd.entity.vo.BaseVo;
import com.zxd.service.ModuleService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * moduleServiceImpl
 * Created by 奕恒 on 2017/2/20 21:54.
 */
@Service
public class ModuleServiceImpl implements ModuleService {

    @Autowired
    private ModuleDao moduleDao;

    @Autowired
    private RoleModuleDao roleModuleDao;

    @Override
    public List<Module> findAll() {
        return moduleDao.findAll();
    }

    @Override
    public Page<Module> find(int pageNum, int pageSize) {
        return moduleDao.findAll(new PageRequest(pageNum - 1, pageSize, Sort.Direction.DESC, "id"));
    }

    @Override
    public Page<Module> find(int pageNum) {
        return find(pageNum, Constant.PAGE_DEF_SIZE);
    }

    @Override
    public Module getById(int id) {
        return moduleDao.findOne(id);
    }

    @Override
    @Transactional
    public void deleteById(int id) {
        for (RoleModule roleModule : roleModuleDao.findListByModuleId(id)) {
            roleModuleDao.delete(roleModule.getId());
        }

        moduleDao.delete(id);
    }

    @Override
    public Module create(Module module) {
        return moduleDao.save(module);
    }

    @Override
    public Module update(Module module) {
        return moduleDao.save(module);
    }

    @Override
    @Transactional
    public void deleteAll(int[] ids) {
        for (int id : ids) {
            deleteById(id);
        }
    }

    @Override
    public BaseVo getMenuData(final String keyWord, Integer pageNum, Integer pageSize) {
        List<Map<String, Object>> list = new ArrayList<>();
        Map<String, Object> map;

        List<Module> moduleList = findListByParams(keyWord, pageNum, pageSize);

        if (pageNum > 1 && moduleList.size() == 0) {
            moduleList = findListByParams(keyWord, pageNum - 1, pageSize);
        }

        for (Module module : moduleList) {
            map = new HashMap<>();
            map.put("id", module.getId());
            map.put("name", module.getName());
            map.put("url", module.getUrl());
            map.put("iconUrl", module.getIconUrl());
            map.put("parentId", module.getParentId());
            map.put("parentModule", module.getParentId().equals(Constant.CHECK_STATUS_DEFAULT) ? new Module() : moduleDao.findOne(module.getParentId()));
            map.put("childSize", moduleDao.findListByParentId(module.getId()).size());

            list.add(map);
        }

        BaseVo baseVo = new BaseVo();
        baseVo.setCount(findListByParams(keyWord, 1, 100000).size());
        baseVo.setData(list);

        return baseVo;
    }

    private List<Module> findListByParams(final String keyWord, Integer pageNum, Integer pageSize) {
        return moduleDao.findAll((root, query, cb) -> {
            Predicate result = null;
            List<Predicate> predicateList = new ArrayList<>();

            if (StringUtils.isNotBlank(keyWord)) {
                predicateList.add(cb.like(root.get("name").as(String.class), "%" + keyWord + "%"));
            }

            if (predicateList.size() > 0) {
                result = cb.and(predicateList.toArray(new Predicate[]{}));
            }
            if (result != null) {
                query.where(result);
            }
            return query.getGroupRestriction();
        }, new PageRequest(pageNum - 1, pageSize, Sort.Direction.ASC, "parentId", "id")).getContent();
    }

    @Override
    public List<Module> findListByParentId(Integer parentId) {
        return moduleDao.findListByParentId(parentId);
    }

    @Override
    public List<Module> findListNoParentId(Integer roleId) {
        List<Module> list = moduleDao.findAll();
        List<RoleModule> roleModuleList = roleModuleDao.findListByRoleId(roleId);

        for (Module module : list) {
            for (RoleModule roleModule : roleModuleList) {
                if (roleModule.getModule().getId().equals(module.getId())) {
                    module.setIsCheck(Constant.CHECK_STATUS_SUCCESS);
                }
            }
        }

        return list;
    }

    @Override
    public Integer saveMenu(Module module) {
        boolean flag = null == module.getId();

        Module tempModule = moduleDao.findOneByName(module.getName());

        if ((null != tempModule && flag) || (null != tempModule && null != module.getId() && !module.getId().equals(tempModule.getId()))) {
            return -1;
        }

        moduleDao.save(module);

        if (flag) {
            // 默认添加到超级管理员权限下
            Role role = new Role();
            role.setId(Constant.CHECK_STATUS_SUCCESS);

            RoleModule roleModule = new RoleModule();
            roleModule.setModule(module);
            roleModule.setRole(role);

            roleModuleDao.save(roleModule);
        }

        return 1;
    }

    @Override
    public Integer batchDel(String ids) {
        for (String s : ids.split(",")) {
            deleteById(Integer.parseInt(s));
        }
        return 1;
    }
}